package groovy.jmx.builder.modelmbean

import groovy.jmx.builder.node.AttrNodeData
import groovy.jmx.builder.node.MBeanNodeData
import javax.management.Descriptor
import javax.management.MBeanAttributeInfo
import javax.management.modelmbean.DescriptorSupport
import javax.management.modelmbean.ModelMBeanAttributeInfo




class ModelMBeanAttributeCollector {
    def static exemptProperties = ['class', 'metaClass']

    public List<ModelMBeanAttributeInfo> collectAttributeInfo(MBeanNodeData data) {
        List<ModelMBeanAttributeInfo> result = []
        List<MetaProperty> properties = data?.object.metaClass.properties
        if (properties) {
            properties.each {prop ->
                if (prop && !exemptProperties.contains(prop.name)) {
                    ModelMBeanAttributeInfo attrInfo;
                    AttrNodeData attr = CollectorHelper.getAttrNodeData(data, prop)
                    if (attr) {
                        attrInfo = getMBeanAttributeInfo(prop, attr)
                        result.add(attrInfo)
                    }
                }
            }
        }
        return result
    }

    public List<ModelMBeanAttributeInfo> collectAttributeInfo(def instance) {
        List<ModelMBeanAttributeInfo> result = []
        List<MetaProperty> properties = instance?.metaClass.properties
        if (properties) {
            properties.each {prop ->
                if (prop && !exemptProperties.contains(prop.name)) {
                    MBeanAttributeInfo attrInfo = getMBeanAttributeInfo(prop)
                    result.add(attrInfo)
                }
            }
        }
        return result
    }

    private ModelMBeanAttributeInfo getMBeanAttributeInfo(MetaProperty property, AttrNodeData data) {
        ModelMBeanAttributeInfo attrInfo;
        if (data && property) {
            Descriptor desc = new DescriptorSupport()
            desc.setField("name", CollectorHelper.capitalize(data.name))
            desc.setField("descriptorType", "attribute")
            desc.setField("displayName", data.description)
            desc.setField("default", data.defaultValue)

            // add any addtional fields
            data?.value.each {key, value ->
                desc.setField(key, value)
            }
            attrInfo = new ModelMBeanAttributeInfo(
                    CollectorHelper.capitalize(data.name),
                    property.type.toString(),
                    data.description,
                    true, // readable
                    data.writable, // writable
                    (property.type instanceof Boolean) // not bolean
            );
            attrInfo.setDescriptor(desc)
        }
        return attrInfo
    }


    private ModelMBeanAttributeInfo getMBeanAttributeInfo(MetaProperty property) {
        ModelMBeanAttributeInfo attrInfo;
        if (property) {
            Descriptor desc = new DescriptorSupport()
            desc.setField("name", CollectorHelper.capitalize(property.name))
            desc.setField("descriptorType", "attribute")
            desc.setField("displayName", property.type.name)

            attrInfo = new ModelMBeanAttributeInfo(
                    CollectorHelper.capitalize(property.name),
                    property.type.name,
                    property.type.name,
                    true, // readable
                    false, // writable
                    (property.type instanceof Boolean) // not bolean
            );
            attrInfo.setDescriptor(desc)
        }
        return attrInfo
    }
}